﻿using System;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using System.Web.Mvc;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using TicketMaster.Web.Models;
using TicketMaster.Web.Models.Reservation;
using System.Collections.Generic;
using TicketMaster.Services;

namespace TicketMaster.Web.Controllers
{
    [Authorize]
    public class ReservationController : BaseController
    {
        public ActionResult Index()
        {
            ReservationStepOne model = new ReservationStepOne();
            model.FromCities = new List<SelectListItem>();
            model.ToCities = new List<SelectListItem>();
            model.Cities = new Dictionary<int, City>();
            var cities = Data.Cities.All().ToList();

            foreach (var x_city in cities)
            {
                Models.City city = new City();
                mapCityObjectToModel(x_city, city);
                model.FromCities.Add(new SelectListItem()
                {
                    Text = city.Name,
                    Value = city.ID.ToString()
                });
                model.ToCities.Add(new SelectListItem()
                {
                    Text = city.Name,
                    Value = city.ID.ToString()
                });
                model.Cities.Add(city.ID, city);
            }

            return View("Index", model);
        }

        public ActionResult FindRoutes(ReservationStepOne model)
        {
            ReservationStepTwo resStepTwo = new ReservationStepTwo();

            Object.City from = Data.Cities.GetById(Int32.Parse(model.FromCityID));
            Object.City to =  Data.Cities.GetById(Int32.Parse(model.ToCityID));
            mapCityObjectToModel(from, resStepTwo.FromCity);
            mapCityObjectToModel(to, resStepTwo.ToCity);

            ReservationPathSelector mngr = new ReservationPathSelector();
            List<Object.Route> routes = mngr.getPath(from, to);
            List<int> routesIDs = routes.Select(x => x.Id).ToList();

            for (int i = 0; i < routes.Count - 1; i++)
			{
                var waypoint = routes[i].EndPoint;

                Models.City city = new City();
                mapCityObjectToModel(waypoint, city);
                resStepTwo.WaypointCities.Add(city);
            }

            var buses = Data.Buses.All().Where(x => routesIDs.Contains(x.RouteId)).ToList();
            foreach (var bus in buses)
            {
                Models.Bus mBus = new Bus();
                mapMapObjectToModel(bus, mBus);
                resStepTwo.Buses.Add(mBus);
            }
            return View("ChooseRoute", resStepTwo);
           
        }

        public ActionResult AddCity()
        {
            Models.City model = new City();
            return View(model);
        }

        public ActionResult AddBus()
        {
            Models.Bus model = new Bus();
            return View(model);
        }

        public ActionResult AddRoute()
        {
            AddRoute model_route = new AddRoute();
            model_route.FromCities = new List<SelectListItem>();
            model_route.ToCities = new List<SelectListItem>();
            model_route.Cities = new Dictionary<int, City>();
            var cities = Data.Cities.All().ToList();

            foreach (var x_city in cities)
            {
                Models.City city = new City();
                mapCityObjectToModel(x_city, city);
                model_route.FromCities.Add(new SelectListItem()
                {
                    Text = city.Name,
                    Value = city.ID.ToString()
                });
                model_route.ToCities.Add(new SelectListItem()
                {
                    Text = city.Name,
                    Value = city.ID.ToString()
                });
                model_route.Cities.Add(city.ID, city);
            }

            return View("AddRoute", model_route);
        }

        public ActionResult SaveCity(Models.City model)
        {
            Object.City x_city = new Object.City();
            mapCityModelToObject(model, x_city);
            Data.Cities.Add(x_city);
            Data.SaveChanges();

            return RedirectToAction("Index", "Home");
        }
        public ActionResult ShowSeats(int busID, int  routeID, int  merchantID) 
        {
            ReservationStepThree model = new ReservationStepThree();
            var seats = Data.Seats.All().Where(x => x.BusId == busID).OrderBy(x => x.SeatNumber);
            model.UserID = User.Identity.GetUserId();
            foreach (var seat in seats)
            {
                Models.Seat mSeat = new Seat();
                mapSeatObjectToModel(seat, mSeat);
                model.Seats.Add(mSeat);
            }


            return View("ShowSeats", model);
        }

        public ActionResult BookSeat(int seatID)
        {
            object obj = new object();
            lock (obj)
	        {
                Object.Seat seat = new Object.Seat();
                seat.Id = seatID;
                seat.IsFree = false;

                Data.Seats.Update(seat);
                
                Object.BookedSeat book = new Object.BookedSeat();
                book.SeatId = seatID;
                book.BookerId = User.Identity.GetUserId();

                Data.BookedSeats.Add(book);

                Data.SaveChanges();
	        }

            return RedirectToAction("Index", "Home");
        }

        public ActionResult SaveBus(Models.Bus model)
        {
            Object.Bus bus = new Object.Bus();
            mapBusModelToObject(model, bus);
            Data.Buses.Add(bus);
            Data.SaveChanges();

            return RedirectToAction("Index", "Home");
        }

        public ActionResult SaveRoute(Models.AddRoute model)
        {
            Object.Route route = new Object.Route();
            mapRouteModelToObject(model, route);
            Data.Routes.Add(route);
            Data.SaveChanges();

            return RedirectToAction("Index", "Home");
        }

        void mapRouteModelToObject(Models.AddRoute source, Object.Route destination)
        {
            TicketMaster.Data.ApplicationDbContext rep = new TicketMaster.Data.ApplicationDbContext();
            destination.StartPointId = rep.Cities.Find(Int32.Parse(source.FromCityID)).Name;
            destination.StartPoint = rep.Cities.Find(Int32.Parse(source.FromCityID));
            destination.EndPointId = rep.Cities.Find(Int32.Parse(source.ToCityID)).Name;
            destination.EndPoint = rep.Cities.Find(Int32.Parse(source.ToCityID));
            /*destination.StartPoint = new TicketMaster.Data.UowData().Cities.GetById(Int32.Parse(source.FromCityID)); ; ;
            destination.EndPointId = new TicketMaster.Data.UowData().Cities.GetById(Int32.Parse(source.ToCityID)).Name;
            destination.EndPoint = new TicketMaster.Data.UowData().Cities.GetById(Int32.Parse(source.ToCityID));*/
            destination.Rate = 5.0;
            destination.Distance = source.Distance;
            //destination.Comments = source.Comments;
            //destination.Merchants = source.Merchants;

        }

        void mapBusModelToObject(Models.Bus source, Object.Bus destination)
        {
            destination.Id = source.Id;
            destination.NumberOfSeat = source.NumberOfSeat;
            destination.MerchantId = source.MerchantId;
            destination.DepartureTime = source.DepartureTime;
            destination.Duration = source.Duration;
            destination.Merchant = source.Merchant;
            destination.RouteId = source.RouteId;
            destination.DepartureTime = source.DepartureTime;
            //destination.Route = source.Route;
            //destination.Seats = source.Seats;
        }

        void mapCityObjectToModel(Object.City source, Models.City destination)
        {
            destination.ID = source.Id;
            destination.Latitude = source.Latitude;
            destination.Longitude = source.Longitude;
            destination.Name = source.Name;
        }

        void mapCityModelToObject(Models.City source, Object.City destination)
        {
            destination.Id = source.ID;
            destination.Latitude = source.Latitude;
            destination.Longitude = source.Longitude;
            destination.Name = source.Name;
        }
        void mapMapObjectToModel(Object.Bus source, Models.Bus destination)
        {
            destination.Id = source.Id;
            destination.MerchantId = source.Id;
            destination.MerchantName = source.Merchant.ApplicationUser.Email;
            destination.StartCityName = source.Route.StartPoint.Name;
            destination.EndCityName = source.Route.EndPoint.Name;
            destination.Duration = source.Duration;
        }

        void mapSeatObjectToModel(Object.Seat source, Models.Seat destination)
        {
            destination.ID = source.Id;
            destination.IsFree = source.IsFree;
            destination.Price = source.Price;
            destination.Number = source.SeatNumber;
            destination.BusID = source.BusId;
        }
    }
}